package com.tx.review.thread_.state;

import java.util.concurrent.TimeUnit;

/**
 * 测试线程状态
 *
 * @author ：tx
 * @version:
 */
public class StateDemo {

    private static Object object = new Object();



    public static void main(String[] args) throws InterruptedException {
        //NEW：线程只是创建，没有start就是new状态
//        testNEW();

        //RUNNABLE
//        testRUNNABLE();

//        BLOCKED：在此等待获取锁的过程线程都处于阻塞状态。
//        testBLOCKED();
        //用wait方式证明blocked
        testBLOCKEDofWait();

//        WAITING:join也会让当前状态变为waiting
//        testWAITING();

//        TIMED_WAITING 和TERMINATED
//        testTIMED_WAITING();


    }

    private static void testBLOCKEDofWait() {
        //当线程A用wait释放锁之后，线程B又进入了这个同步代码块，那么就会有Blocked
        Object obj = new Object();
        Thread threadA = new Thread(() -> {
            synchronized (obj) {
                try {
                    //睡一秒之后，等待（释放锁）
                    System.out.println(Thread.currentThread().getName() + " come in ");
                    TimeUnit.SECONDS.sleep(1);
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }, "A");

        Thread threadB = new Thread(() -> {
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + " come in ");
                //唤醒线程A后，但是还睡了3s，这时线程B还没有释放锁，只是唤醒了线程A，所以线程A还在等着锁
                obj.notify();
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B");

        threadA.start();
        threadB.start();
        //睡了两秒，导致线程A执行了wait方法，线程B执行了notify方法，但还在同步代码块里
        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println(threadA.getState());
    }

    private static void testTIMED_WAITING() throws InterruptedException {
        Thread thread = new Thread(() -> {
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
        });
        thread.start();
        Thread.sleep(50);
        System.out.println(thread.getState());
        Thread.sleep(3000);
        System.out.println(thread.getState());
    }

    private static void testWAITING() throws InterruptedException {
        Thread t2 = new Thread(() -> {
            try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println(Thread.currentThread().getName() + "完成");
        });

        Thread t1 = new Thread(() -> {
            try {
                t2.join();
                System.out.println(Thread.currentThread().getName() +"也结束了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t2.start();
        t1.start();
        //由于使用了join不是立即把状态改为waiting，需要一定的时间，所以我们给他时间改变状态
        Thread.sleep(3);
        System.out.println(t1.getState());
    }

    private static void testBLOCKED() throws InterruptedException {
        Thread t1 = new Thread(()->{
            synchronized (object){
                try {
                    Thread.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(()->{
            synchronized (object){
                System.out.println(Thread.currentThread().getName() +" 获得锁进来了");
            }
        });

        t1.start();
        Thread.sleep(50);
        //让t2也进入方法，在获取锁，就是阻塞状态了
        t2.start();
        Thread.sleep(50);
        System.out.println(t2.getState());
    }

    private static void testRUNNABLE() {
        Thread thread = new Thread(()->{
            while (true){
                Thread.yield();
            }
        });
        thread.start();
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println(thread.getState());
    }


    private static void testNEW() {
        Thread thread = new Thread();
        //其实是通过threadStatus来获取枚举类型的
        System.out.println(thread.getState());
    }
}
